package com.vichat.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.net.URLDecoder;

/**
 * Created by ranjx on 2017/6/5.
 */
public class AES {
    private static transient final Logger logger = LoggerFactory.getLogger(AES.class);
    private static final String configCryptKey = "1bccdcf0c075e916";


    static Cipher cipher;


    static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";



    static byte[] getIV() {
        String iv = "19d2a13f39f8f72e"; //IV length: must be 16 bytes long
        return iv.getBytes();
    }

    /**将二进制转换成16进制
     * @param buf
     * @return
     */
    public static String parseByte2HexStr(byte buf[]) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < buf.length; i++) {
            String hex = Integer.toHexString(buf[i] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex.toUpperCase());
        }
        return sb.toString();
    }

    /**将16进制转换为二进制
     * @param hexStr
     * @return
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (hexStr.length() < 1)
            return null;
        byte[] result = new byte[hexStr.length()/2];
        for (int i = 0;i< hexStr.length()/2; i++) {
            int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);
            int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);
            result[i] = (byte) (high * 16 + low);
        }
        return result;
    }

    public static String hexString2binaryString(String hexString)
    {
        if (hexString == null || hexString.length() % 2 != 0)
            return null;
        String bString = "", tmp;
        for (int i = 0; i < hexString.length(); i++)
        {
            tmp = "0000"
                    + Integer.toBinaryString(Integer.parseInt(hexString
                    .substring(i, i + 1), 16));
            bString += tmp.substring(tmp.length() - 4);
        }
        return bString;
    }

    public static String encrypt(String content) throws Exception{
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(configCryptKey.getBytes(), "AES");


        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(getIV()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(content.getBytes()); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return parseByte2HexStr(encrypt);
    }


    public static String encrypt(String content, String secretKey) throws Exception{
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "AES");
        System.out.println("密钥为：" +    parseByte2HexStr(key.getEncoded()));
        System.out.println("密钥的长度为：" + key.getEncoded().length);

        cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(getIV()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(content.getBytes()); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return parseByte2HexStr(encrypt);
    }
    public static String decrypt(String content) throws Exception{
        byte[] byetes = parseHexStr2Byte(content);
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(configCryptKey.getBytes(), "AES");


        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(getIV()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(byetes); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return new String(encrypt);
    }

    public static String decrypt(String content, String secretKey) throws Exception{
        byte[] byetes = parseHexStr2Byte(content);
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "AES");


        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(getIV()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(byetes); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return new String(encrypt);
    }

    public static String decrypt(String content, String secretKey, String iv) throws Exception{
        byte[] byetes = parseHexStr2Byte(content);
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "AES");


        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(byetes); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return new String(encrypt);
    }

    public static String decryptSsoKey(byte[] content, String secretKey, String iv) throws Exception{
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "AES");


        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(content); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return new String(encrypt,"UTF-8");
    }

    public static String decrypt(byte[] byetes, String secretKey, String iv) throws Exception{
        cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
        SecretKeySpec key = new SecretKeySpec(secretKey.getBytes(), "AES");


        cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv.getBytes()));//使用加密模式初始化 密钥
        byte[] encrypt = cipher.doFinal(byetes); //按单部分操作加密或解密数据，或者结束一个多部分操作。
        return new String(encrypt);
    }

    /**
     * 获取Base64字符串
     * @param codestr
     * @return
     * @throws IOException
     */
    public static byte[] getDecodeBase64(String codestr) throws IOException{
        byte[] srcbyte = Base64.decodeBase64(codestr);
        return srcbyte;
    }


    /**
     * 获取解密url的cryptKey
     * @param signalCryptKey
     * @return
     * @throws Exception
     */
    public static String getSignalCryptKey(String signalCryptKey) throws Exception{
        String defaultPass = configCryptKey.substring(0,16);
        String defaultIV = configCryptKey.substring(16,32);
        String cryptKey = AES.decrypt(signalCryptKey, defaultPass, defaultIV);
        return cryptKey;
    }

    /**
     * 获取用户ID
     * @param ssokey
     * @param cryptKey
     * @return
     * @throws IOException
     */
    public static long getUid(String ssokey, String cryptKey) throws IOException {
        long uid=0;
        try{
            String defaultPass = "";
            String defaultIV = "";
            if(StringUtils.isNotBlank(cryptKey)){
                defaultPass = cryptKey.substring(0,16);
                defaultIV = cryptKey.substring(16,32);
            }
            byte[] ssoKeyByte = AES.getDecodeBase64(ssokey);
            String res = AES.decryptSsoKey(ssoKeyByte, defaultPass, defaultIV);
            JSONObject obj = JSON.parseObject(res);
            uid = Long.parseLong(obj.get("uid").toString());
            logger.info("用户UID=" + uid);
        }catch(Exception e){
            logger.error("获取用户uid异常");
        }
        return uid;
    }


    public static void main(String[] args) throws Exception {
      String str=  encrypt("uid=16,time=1538904889584",configCryptKey).toUpperCase();
        System.out.println(str);
        str = decrypt("07F902E13C82FD9C944759004E791871",configCryptKey);
        System.out.println(str);
//        //即聊ssoKey
//        gtalkSsoKeyCrypt();
//        //KKssoKey
//        kkSsoKeyCrypt();
    }

    public static void gtalkSsoKeyCrypt()throws Exception{
        String sysPasswordAndIV = "b16e80c7f7fa545c3987ef638e0042a7643836ee0d573e88b8fb99b2434f50be56d30a3ebbdcaafb5077563b33e42c41";
        String cryptKey = AES.getSignalCryptKey(sysPasswordAndIV);
        System.out.println(cryptKey);

        String ssoKey = "WCWAp9qqE7JvSB2PdwazCM1JTAKu8EFWI6yyoBY9bmcCRbXa24hJrd9wewLtUXCezyTjka5y1PNt1HNeIPpqOTjaYlTwWj7ST-rfj7BbTdNfjjOvAHEGkZFUX7U2FVIJ";
        AES.getUid(ssoKey,cryptKey);
    }

    public static void kkSsoKeyCrypt()throws Exception{
        String sysPasswordAndIV = "5df2949e949966ede9bba55b14dbc494d18cfe4fcc137aba19e3de22ce22372c7a752ea1dab5117ad4f4f0994fc481a7";
        String cryptKey = AES.getSignalCryptKey(sysPasswordAndIV);
        System.out.println(cryptKey);

        String ssoKey = "N8kErUF4qych9CgxzBUDPQ9mW5QX5LOGVDViOstkmkvFKDWkESnGolq-Gw-_SiPQsoUit0jC7bE1vDxyDdwrOt5KDSwPWgNykQr1240IuSmnJYUy2z5NhctuBAhD0rIbXWifO0kx6vN8YvT95eUOL7dvJTcLcGtsNGSDu2UVBBTjUbI5QFo643htwrZzl1SI88JVrjUR4TQe-3KkKMY286kQKBhyp7U46QVRVwb_MwVXWm47QQRkjMpm9AYmWPPZ0QxYZZ56akeuuU-e85_O1w";
        AES.getUid(URLDecoder.decode(ssoKey),cryptKey);
    }
}
